package com.hbnu.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbnu.system.config.BaseException;
import com.hbnu.system.constant.RoleConstant;
import com.hbnu.system.constant.StatusCheckConstant;
import com.hbnu.system.core.base.CommonPage;
import com.hbnu.system.mapper.Tranproject_registrationMapper;
import com.hbnu.system.model.context.BaseContext;
import com.hbnu.system.model.dto.CheckBackDTO;
import com.hbnu.system.model.dto.TranProjectTSdto;
import com.hbnu.system.model.dto.Tranproject_registrationDTO;
import com.hbnu.system.model.entity.*;
import com.hbnu.system.model.query.TranProjectExportQuery;
import com.hbnu.system.model.query.TranProjectPageQuery;
import com.hbnu.system.model.vo.ExportTranProjectVO;
import com.hbnu.system.service.*;
import com.hbnu.system.utils.AuditUtils;
import com.hbnu.system.utils.CheckRoleUtil;
import com.hbnu.system.utils.UserInfoUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2023-05-16
 */
@Service
public class Tranproject_registrationServiceImpl extends ServiceImpl<Tranproject_registrationMapper, Tranproject_registration> implements ITranproject_registrationService {
    @Autowired
    ITranproject_registrationService iTranproject_registrationService;

    @Autowired
    IUserService iUserService;

    @Autowired
    AuditService auditService;

    @Autowired
    IdToStatsService idToStatsService;

    @Autowired
    private TranprojectfileService tranprojectfileService;

    @Autowired
    private IProjectQualificationService iProjectQualificationService;

    @Autowired
    private TranprojectauthorService tranprojectauthorService;

    @Autowired
    private DZfundsService dzZfundsService;

    @Autowired
    private ZCfundsService zcZfundsService;

    @Autowired
    private CheckRoleUtil checkRoleUtil;

    @Autowired
    private Validator validator;

    @Autowired
    private UserInfoUtils userInfoUtils;

    @Autowired
    private IDeptService iDeptService;


    /**
     * 添加横向项目
     * @param tranprojectRegistrationDTO 横向项目
     * @return  boolean
     */
    @Override
    public boolean addTranproject(Tranproject_registrationDTO tranprojectRegistrationDTO) {
        Tranproject_registration tranprojectRegistration = BeanUtil.copyProperties(tranprojectRegistrationDTO, Tranproject_registration.class);
        //校验项目名称唯一性

        tranprojectRegistration.setProjectState(StatusCheckConstant.DRAFT);
        tranprojectRegistration.setEducation(tranprojectRegistrationDTO.getEducation());
        tranprojectRegistration.setEnteredDate(LocalDateTime.now());
        tranprojectRegistration.setUnit("湖北师范大学");
        tranprojectRegistration.setFinancialNum(tranprojectRegistrationDTO.getFinancialNum());
        tranprojectRegistration.setAccount(tranprojectRegistrationDTO.getAccount());
        //tranprojectRegistrationDTO.getProjectFlag()为空进行下面操作
        if (tranprojectRegistrationDTO.getProjectFlag() == null) {
            tranprojectRegistration.setProjectFlag(2);
        }
        // 设置横向项目实体字段
        setTranprojectFields(tranprojectRegistrationDTO, tranprojectRegistration);

        return baseMapper.insert(tranprojectRegistration) == 1;
    }

    /**
     * 暂存横向项目数据
     * @param tranProjectTSdto 横向项目暂存数据
     * @return 是否成功
     */
    @Override
    public boolean saveDraftTranProject(TranProjectTSdto tranProjectTSdto) {
        // 创建项目实体对象
        Tranproject_registration project = new Tranproject_registration();
        // 复制属性
        BeanUtil.copyProperties(tranProjectTSdto, project);
        
        // 设置录入日期
        if (project.getEnteredDate() == null) {
            project.setEnteredDate(LocalDateTime.now());
        }
        
        // 设置状态为草稿（如果未设置）
        if (project.getProjectState() == null || project.getProjectState().trim().isEmpty()) {
            project.setProjectState("草稿");
        }
        
        // 设置默认值
        if (project.getProjectFlag() == null) {
            project.setProjectFlag(2); // 默认横向项目
        }
        
        // 设置承担单位
        if (project.getUnit() == null || project.getUnit().trim().isEmpty()) {
            project.setUnit("湖北师范大学");
        }

        // 负责人工号转UID
        if (project.getAccount() != null && !project.getAccount().trim().isEmpty()) {
            User headUser = iUserService.getUserByAccount(project.getAccount());
            project.setHead(headUser.getUid());
        }

        // 多值字段用逗号拼接
        List<String> sourceEnterpriseCategory = tranProjectTSdto.getSourceEnterpriseCategory();
        if (sourceEnterpriseCategory != null) {
            project.setSourceEnterpriseCategory(String.join(",", sourceEnterpriseCategory));
        } else {
            project.setSourceEnterpriseCategory("");
        }

        String projectSourceUnitId = tranProjectTSdto.getProjectSourceUnitId();
        project.setProjectSourceUnitId(projectSourceUnitId != null ? projectSourceUnitId : "");

        
        // 处理ID：如果有ID则更新，无ID则新增
        if (project.getTRegistrationID() != null && !project.getTRegistrationID().isEmpty()) {
            // 检查项目是否存在
            Tranproject_registration existingProject = this.getById(project.getTRegistrationID());
            if (existingProject != null) {
                // 更新项目
                return this.updateById(project);
            } else {
                // 项目不存在，进行新增
                return this.save(project);
            }
        } else {
            // 使用雪花算法生成唯一ID
            Snowflake snowflake = IdUtil.getSnowflake(1, 1);
            project.setTRegistrationID(String.valueOf(snowflake.nextId()));
            // 新增项目
            return this.save(project);
        }
    }


    /**
     * 删除横向项目
     * @param TRegistrationID 横向项目编号
     * @return  删除结果
     */
    @Override
    public boolean deleteTranproject(String TRegistrationID) throws IOException {
        Tranproject_registration tranproject = super.getOne(Wrappers.lambdaQuery(Tranproject_registration.class)
                .eq(Tranproject_registration::getTRegistrationID, TRegistrationID));
        if (Objects.isNull(tranproject)) {
            throw new BaseException("横向合同编号有误!");
        }

        // 校验操作权限
        checkRoleUtil.checkPermissionProject(tranproject.getProjectState());

        // 删除关联数据
        deleteRelatedData(TRegistrationID);

        return baseMapper.deleteById(TRegistrationID) == 1;
    }


    /**
     * 修改横向项目
     * @param tranprojectRegistrationDTO 横向项目
     * @return  boolean
     */
    @Override
    public boolean updateTranproject(Tranproject_registrationDTO tranprojectRegistrationDTO) {
        Tranproject_registration tranproject = BeanUtil.copyProperties(tranprojectRegistrationDTO, Tranproject_registration.class);

        // 校验操作权限
        checkRoleUtil.checkPermissionProject(tranproject.getProjectState());

        // 设置横向项目实体字段
        setTranprojectFields(tranprojectRegistrationDTO, tranproject);

        return baseMapper.updateById(tranproject) == 1;
    }


    /**
     * 获取横向项目详情——不对接前端
     * @param tranprojectID 横向项目编号
     * @return  横向项目实体
     */
    @Override
    public Tranproject_registration getTranproject(String tranprojectID) {
        Tranproject_registration one = super.getOne(Wrappers.lambdaQuery(Tranproject_registration.class)
                .eq(Tranproject_registration::getTRegistrationID, tranprojectID));
        if (Objects.isNull(one)) {
            throw new BaseException("横向合同编号异常!未查找到该横向项目");
        }
        return one;
    }


    /**
     * 获取横向项目详情——对接前端
     * @param tranprojectID 横向项目编号
     * @return  横向项目DTO
     */
    @Override
    public Tranproject_registration getTranprojectDTOByID(String tranprojectID) {
        Tranproject_registration one = super.getOne(Wrappers.lambdaQuery(Tranproject_registration.class)
                .eq(Tranproject_registration::getTRegistrationID, tranprojectID));
        if (Objects.isNull(one)) {
            throw new BaseException("横向合同编号异常!未查找到该横向项目");
        }
        //将录入人的id转成名字
        String entered = idToStatsService.IdToName(one.getEntered());
        one.setEntered(entered);
        //根据负责人id找到负责人的工号，增加空值检查
        User user = iUserService.lambdaQuery().eq(User::getUid, one.getHead()).one();
        if (Objects.nonNull(user)) {
            one.setAccount(user.getAccount());
        } else {
            one.setAccount("未知工号");
        }
        return one;
    }


    /**
     * 获取横向项目列表（分页）
     * @param tranProjectPageQuery 查询参数
     * @return  分页结果
     */
    @Override
    public CommonPage<Tranproject_registration> userGetProjects(TranProjectPageQuery tranProjectPageQuery) {
        String userId = BaseContext.getCurrentId();
        User user = iUserService.getById(userId);

        // 构建分页对象
        Page<Tranproject_registration> page = new Page<>(tranProjectPageQuery.getPageNum(), tranProjectPageQuery.getPageSize());
        IPage<Tranproject_registration> tranprojectIPage = queryTranProjects(page, tranProjectPageQuery, user, false);

        return buildCommonPage(tranprojectIPage, false);
    }

    /**
     * 导出文件
     *
     * @param tranProjectPageQuery 查询条件
     * @return 导出的文件
     */
    @Override
    public CommonPage<Tranproject_registration> export(TranProjectPageQuery tranProjectPageQuery) {
        String userId = BaseContext.getCurrentId();
        User user = iUserService.getById(userId);

        // 构建分页对象
        Page<Tranproject_registration> page = new Page<>(tranProjectPageQuery.getPageNum(), tranProjectPageQuery.getPageSize());
        IPage<Tranproject_registration> tranprojectIPage = queryTranProjects(page, tranProjectPageQuery, user, true);

        return buildCommonPage(tranprojectIPage, true);
    }

    /**
     * 导出横向项目
     *
     * @param tranProjectExportQuery 查询条件
     * @return 导出的文件
     */
    @Override
    public List<ExportTranProjectVO> exportTranProject(TranProjectExportQuery tranProjectExportQuery) {
        String userId = BaseContext.getCurrentId();
        User user = iUserService.getById(userId);
        List<ExportTranProjectVO> exportTranProjectVOList=null;
        //根据角色执行不同查询
        if (user.getRole().equals(RoleConstant.ROLE_ADMIN_SCHOOL)){
             exportTranProjectVOList= baseMapper.schoolExportTranProject(tranProjectExportQuery,user);
        } else if (user.getRole().equals(RoleConstant.ROLE_ADMIN_COLLEGE)) {
            // 院级审核员只能导出自己学院的项目
            // 通过user中的dept属性，从dept表中查询deptName
            Dept dept = iDeptService.getById(user.getDept());
            if (dept != null) {
                user.setDeptName(dept.getDeptName());
            }
            exportTranProjectVOList = baseMapper.collegeExportTranProject(tranProjectExportQuery, user);
        } else {
            exportTranProjectVOList = baseMapper.userExportTranProject(tranProjectExportQuery,user);
        }
        //判空
        if(exportTranProjectVOList==null){
            return new ArrayList<>();
        }
        //遍历
        for (ExportTranProjectVO exportTranProjectVO : exportTranProjectVOList) {
            exportTranProjectVO.setAccount(iUserService.getById(exportTranProjectVO.getHead()).getAccount());
            List<Tranprojectauthor> authors = tranprojectauthorService.list(new QueryWrapper<Tranprojectauthor>().eq("TRegistrationID", exportTranProjectVO.getTRegistrationID()));
            //将Authors的名字用逗号分隔拼接，并设置
            exportTranProjectVO.setProjectMembers(authors.stream().map(Tranprojectauthor::getName).collect(Collectors.joining(",")));
        }
        return exportTranProjectVOList;
    }

    /**
     * 查询横向项目
     * @param page 分页对象
     * @param tranProjectPageQuery 查询参数
     * @param user 当前用户
     * @param isExport 是否为导出操作
     * @return 查询结果
     */
    private IPage<Tranproject_registration> queryTranProjects(Page<Tranproject_registration> page,
                                                              TranProjectPageQuery tranProjectPageQuery,
                                                              User user,
                                                              boolean isExport) {
        if (user.getRole().equals(RoleConstant.ROLE_ADMIN_SCHOOL)) {
            return isExport ?
                    baseMapper.schoolExportRelateTranprojectQuery(page, tranProjectPageQuery, user) :
                    baseMapper.schoolGetRelateTranprojectQuery(page, tranProjectPageQuery, user);
        } else if (user.getRole().equals(RoleConstant.ROLE_ADMIN_COLLEGE)) {
            // 通过user中的dept属性，从dept表中查询deptName
            Dept dept = iDeptService.getById(user.getDept());
            if (dept != null) {
                user.setDeptName(dept.getDeptName());
            }
            return isExport ?
                    baseMapper.collegeExportRelateTranprojectQuery(page, tranProjectPageQuery, user) :
                    baseMapper.collegeGetRelateTranprojectQuery(page, tranProjectPageQuery, user);
        } else {
            return isExport ?
                    baseMapper.userExportRelateTranprojectQuery(page, tranProjectPageQuery, user) :
                    baseMapper.userGetRelateTranprojectQuery(page, tranProjectPageQuery, user);
        }
    }

    /**
     * 构建通用分页结果
     * @param tranprojectIPage 查询结果
     * @param isExport 是否为导出操作
     * @return 通用分页结果
     */
    private CommonPage<Tranproject_registration> buildCommonPage(IPage<Tranproject_registration> tranprojectIPage, boolean isExport) {
        CommonPage<Tranproject_registration> commonPage = CommonPage.restPage(tranprojectIPage);
        List<Tranproject_registration> records = tranprojectIPage.getRecords();

        float totalScore = 0;
        for (Tranproject_registration record : records) {
            totalScore += record.getScore();

            // 导出时需要设置额外字段
            if (isExport) {
                User user = iUserService.getById(record.getHead());
                record.setAccount(user.getAccount());
                List<Tranprojectauthor> Authors = tranprojectauthorService.list(new QueryWrapper<Tranprojectauthor>().eq("TRegistrationID", record.getTRegistrationID()));
                //将Authors的名字用逗号分隔拼接，并设置
                record.setProjectMembers(Authors.stream().map(Tranprojectauthor::getName).collect(Collectors.joining(",")));
            }
        }

        commonPage.setFigure(totalScore);
        commonPage.setList(records);

        return commonPage;
    }



    /**
     * 横向在研申请
     * @param tranprojectID 横向项目编号
     * @return  提交结果
     */
    @Override
    public Boolean CommitTranproject(String tranprojectID) {
        // 校验项目及字段
        Tranproject_registration tranproject = validateTranProjectRegistration(tranprojectID);

        // 校验项目状态
        if (!Arrays.asList(
                StatusCheckConstant.DRAFT,
                StatusCheckConstant.PROJECT_FINISH_BACK,
                StatusCheckConstant.IN_PROGRESS_BACK
        ).contains(tranproject.getProjectState())) {
            throw new BaseException("该横向项目不适用于该阶段!");
        }

        // 检查量化分数是否填写
        Project_Qualification qualification = iProjectQualificationService.getOne(
                Wrappers.lambdaQuery(Project_Qualification.class)
                        .eq(Project_Qualification::getProjectID, tranprojectID)
        );
        if (Objects.isNull(qualification)) {
            throw new BaseException("请先填写横向项目的量化分数!");
        }

        // 检查作者列表是否填写
        List<Tranprojectauthor> authorList = tranprojectauthorService.list(
                Wrappers.lambdaQuery(Tranprojectauthor.class)
                        .eq(Tranprojectauthor::getTregistrationid, tranprojectID)
        );
        if (CollectionUtils.isEmpty(authorList)) {
            throw new BaseException("请先添加横向项目的作者信息!");
        }

        // 更新状态 - 提交到院级审核
        tranproject.setProjectState(StatusCheckConstant.IN_PROGRESS_WAIT_COLLEGE_CHECK);
        tranproject.setReason("");
        return baseMapper.updateById(tranproject) == 1;
    }

    /**
     * 横向项目在研院级审核通过
     * @param token 用户token
     * @param tranprojectID 横向项目编号
     * @return 审核结果
     */
    @Override
    public Boolean collegeCheckPass(String token, String tranprojectID) {
        // 1. 查询并校验项目
        Tranproject_registration tranproject = iTranproject_registrationService.getTranproject(tranprojectID);
        if (Objects.isNull(tranproject)) {
            throw new BaseException("该横向项目编号有误!");
        }

        // 2. 校验项目状态 - 院级审核通过需要检查是否处于待院审核状态
        if (!tranproject.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该横向项目状态不处于该环节!");
        }

        // 3. 更新项目状态 - 提交到校级审核
        tranproject.setProjectState(StatusCheckConstant.IN_PROGRESS_WAIT_SCHOOL_CHECK);

        // 4. 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 构建并保存审核记录
        Audit audit = AuditUtils.buildAudit(
                tranprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                "在研待院审核->在研待校审核",
                StatusCheckConstant.PASS
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(tranproject) == 1;
    }

    /**
     * 横向项目在研院级审核打回
     * @param token 用户token
     * @param checkBackDTO 打回参数
     * @return 审核结果
     */
    @Override
    public Boolean collegeCheckBack(String token, CheckBackDTO checkBackDTO) {
        String tranprojectID = checkBackDTO.getID();
        // 1. 查询并校验项目
        Tranproject_registration tranproject = iTranproject_registrationService.getTranproject(tranprojectID);
        if (Objects.isNull(tranproject)) {
            throw new BaseException("该横向项目编号有误!");
        }

        // 2. 校验项目状态 - 院级审核退回需要检查是否处于待院审核状态
        if (!tranproject.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该横向项目状态不处于该环节!");
        }

        // 3. 更新状态及原因
        tranproject.setProjectState(StatusCheckConstant.IN_PROGRESS_BACK);
        tranproject.setReason(checkBackDTO.getReason());

        // 4. 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 添加审核记录
        Audit audit = AuditUtils.buildAudit(
                tranprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                "在研待院审核->项目在研退回",
                checkBackDTO.getReason()
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(tranproject) == 1;
    }


    /**
     * 横向在研校级审核通过
     * @param token 用户token
     * @param tranprojectID 横向项目编号
     * @return  审核结果
     */
    @Override
    public Boolean schoolCheckPass(String token, String tranprojectID) {
        // 查询并校验项目
        Tranproject_registration tranproject = iTranproject_registrationService.getTranproject(tranprojectID);
        if (Objects.isNull(tranproject)) {
            throw new BaseException("该横向合同编号有误!");
        }

        // 校验项目状态 - 校级审核通过需要检查是否处于待校审核状态
        if (!tranproject.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_SCHOOL_CHECK)
        || tranproject.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该项目状态不处于该环节!");
        }

        // 更新项目状态
        tranproject.setProjectState(StatusCheckConstant.IN_PROGRESS);

        // 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 添加审核记录
        Audit audit = AuditUtils.buildAudit(
                tranprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                tranproject.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_SCHOOL_CHECK) ? "在研待校审核->项目在研" : "在研待院审核->在研待校审核",
                StatusCheckConstant.PASS
        );
        auditService.addAudit(audit);

        return baseMapper.updateById(tranproject) == 1;
    }


    /**
     * 横向在研校级审核打回
     * @param token 用户token
     * @param checkBackDTO 打回参数
     * @return  审核结果
     */
    @Override
    public Boolean schoolCheckBack(String token, CheckBackDTO checkBackDTO) {
        String tranprojectID = checkBackDTO.getID();
        // 查询并校验项目
        Tranproject_registration tranproject = iTranproject_registrationService.getTranproject(tranprojectID);
        if (Objects.isNull(tranproject)) {
            throw new BaseException("该横向合同编号有误!");
        }
        String projectState = tranproject.getProjectState();
        // 更新状态及原因
        tranproject.setProjectState(StatusCheckConstant.IN_PROGRESS_BACK);
        tranproject.setReason(checkBackDTO.getReason());

        // 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 添加审核记录
        Audit audit = AuditUtils.buildAudit(
                tranprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                projectState + "->项目在研退回",
                checkBackDTO.getReason()
        );
        auditService.addAudit(audit);

        return baseMapper.updateById(tranproject) == 1;
    }


    /**
     * 提交横向项目结题申请
     * @param tranprojectID 横向项目编号
     * @return  提交结果
     */
    @Override
    public Boolean CommitTranprojectFinish(String tranprojectID) {
        // 校验项目及字段
        Tranproject_registration tranproject = validateTranProjectRegistration(tranprojectID);

        // 校验项目状态
        if (!Arrays.asList(
                StatusCheckConstant.DRAFT,
                StatusCheckConstant.IN_PROGRESS,
                StatusCheckConstant.IN_PROGRESS_BACK,
                StatusCheckConstant.PROJECT_FINISH_BACK
        ).contains(tranproject.getProjectState())) {
            throw new BaseException("该横向项目不适用于该阶段!");
        }

        // 检查量化分数是否填写
        Project_Qualification qualification = iProjectQualificationService.getOne(
                Wrappers.lambdaQuery(Project_Qualification.class)
                        .eq(Project_Qualification::getProjectID, tranprojectID)
        );
        if (Objects.isNull(qualification)) {
            throw new BaseException("请先填写横向项目的量化分数!");
        }

        // 更新状态 - 提交到院级审核
        tranproject.setProjectState(StatusCheckConstant.FINISH_WAIT_COLLEGE_CHECK);
        return baseMapper.updateById(tranproject) == 1;
    }

    /**
     * 横向项目结题院级审核通过
     * @param token 用户token
     * @param tranprojectID 横向项目编号
     * @return 审核结果
     */
    @Override
    public Boolean collegeFinishCheckPass(String token, String tranprojectID) {
        // 1. 查询并校验项目
        Tranproject_registration tranproject = iTranproject_registrationService.getTranproject(tranprojectID);
        if (Objects.isNull(tranproject)) {
            throw new BaseException("该横向项目编号有误!");
        }

        // 2. 校验项目状态 - 院级审核通过需要检查是否处于待院审核状态
        if (!tranproject.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该横向项目状态不处于该环节!");
        }

        // 3. 更新项目状态 - 提交到校级审核
        tranproject.setProjectState(StatusCheckConstant.FINISH_WAIT_SCHOOL_CHECK);

        // 4. 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 构建并保存审核记录
        Audit audit = AuditUtils.buildAudit(
                tranprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                "结题待院审核->结题待校审核",
                StatusCheckConstant.PASS
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(tranproject) == 1;
    }

    /**
     * 横向项目结题院级审核打回
     * @param token 用户token
     * @param checkBackDTO 打回参数
     * @return 审核结果
     */
    @Override
    public Boolean collegeFinishCheckBack(String token, CheckBackDTO checkBackDTO) {
        String tranprojectID = checkBackDTO.getID();
        // 1. 查询并校验项目
        Tranproject_registration tranproject = iTranproject_registrationService.getTranproject(tranprojectID);
        if (Objects.isNull(tranproject)) {
            throw new BaseException("该横向项目编号有误!");
        }

        // 2. 校验项目状态 - 院级审核退回需要检查是否处于待院审核状态
        if (!tranproject.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该横向项目状态不处于该环节!");
        }

        // 3. 更新状态及原因
        tranproject.setProjectState(StatusCheckConstant.PROJECT_FINISH_BACK);
        tranproject.setReason(checkBackDTO.getReason());

        // 4. 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 添加审核记录
        Audit audit = AuditUtils.buildAudit(
                tranprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                "结题待院审核->项目结题退回",
                checkBackDTO.getReason()
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(tranproject) == 1;
    }


    /**
     * 横向项目结题校级审核通过
     * @param token 用户token
     * @param tranprojectID 横向项目编号
     * @return  审核结果
     */
    @Override
    public Boolean schoolFinishCheckPass(String token, String tranprojectID) {
        // 查询并校验项目
        Tranproject_registration tranproject = iTranproject_registrationService.getTranproject(tranprojectID);
        if (Objects.isNull(tranproject)) {
            throw new BaseException("该横向合同编号有误!");
        }

        // 校验项目状态 - 校级审核通过需要检查是否处于待校审核状态
        if (!tranproject.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_SCHOOL_CHECK)
        || !tranproject.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该项目状态不处于该环节!");
        }

        // 更新状态
        tranproject.setProjectState(StatusCheckConstant.PROJECT_FINISH);
        tranproject.setReason("");


        // 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 添加审核记录
        Audit audit = AuditUtils.buildAudit(
                tranprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                tranproject.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_SCHOOL_CHECK) ? "结题待校审核->项目结题" : "结题待院审核->结题待校审核",
                StatusCheckConstant.PASS
        );
        auditService.addAudit(audit);

        return baseMapper.updateById(tranproject) == 1;
    }


    /**
     * 横向项目结题校级审核打回
     * @param token 用户token
     * @param checkBackDTO 打回参数
     * @return  审核结果
     */
    @Override
    public Boolean schoolFinishCheckBack(String token, CheckBackDTO checkBackDTO) {
        String tranprojectID = checkBackDTO.getID();
        // 查询并校验项目
        Tranproject_registration tranproject = iTranproject_registrationService.getTranproject(tranprojectID);
        if (Objects.isNull(tranproject)) {
            throw new BaseException("该横向合同编号有误!");
        }

        String projectState = tranproject.getProjectState();

        // 更新状态及原因
        tranproject.setProjectState(StatusCheckConstant.PROJECT_FINISH_BACK);
        tranproject.setReason(checkBackDTO.getReason());

        // 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 添加审核记录
        Audit audit = AuditUtils.buildAudit(
                tranprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                projectState + "->项目结题退回",
                checkBackDTO.getReason()
        );
        auditService.addAudit(audit);

        return baseMapper.updateById(tranproject) == 1;
    }
    
    /**
     * 在研项目撤回
     * @param token 用户token
     * @param tranProjectID 横向项目编号
     * @return 撤回结果
     */
    @Override
    public Boolean withdrawHxProject(String token, String tranProjectID) {
        // 1. 查询并校验项目
        Tranproject_registration tranproject = iTranproject_registrationService.getTranproject(tranProjectID);
        if (Objects.isNull(tranproject)) {
            throw new BaseException("该横向项目编号有误!");
        }

        // 2. 校验项目状态 - 只有在研待院审核和结题待院审核才能撤回
        String projectState = tranproject.getProjectState();
        if (!(projectState.equals(StatusCheckConstant.IN_PROGRESS_WAIT_COLLEGE_CHECK)
                || projectState.equals(StatusCheckConstant.FINISH_WAIT_COLLEGE_CHECK))) {
            throw new BaseException("只有在研待院审核和结题待院审核的项目才能撤回!");
        }

        // 3. 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();
        String roleName = currentUser.getRoleName();

        // 4. 更新项目状态为草稿
        tranproject.setProjectState(StatusCheckConstant.DRAFT);

        // 5. 构建并保存审核记录
        Audit audit = AuditUtils.buildAudit(
                tranProjectID,
                roleName,
                currentUser.getUserName(),
                tranproject.getProjectState() + "->项目撤回",
                "用户撤回申请"
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(tranproject) == 1;
    }


    /**
     * 校验横向项目业务规则及字段合法性
     */
    private Tranproject_registration validateTranProjectRegistration(String tranprojectID) {
        Tranproject_registration tranproject = getTranproject(tranprojectID);

        // 转换为DTO并执行注解校验
        Tranproject_registrationDTO dto = BeanUtil.copyProperties(tranproject, Tranproject_registrationDTO.class);
        Set<ConstraintViolation<Tranproject_registrationDTO>> violations = validator.validate(dto);

        // 校验失败抛出异常
        if (!violations.isEmpty()) {
            String errorMsg = violations.iterator().next().getMessage();
            throw new BaseException(errorMsg);
        }

        return tranproject;
    }


    /**
     * 设置横向项目实体字段（负责人UID、多值字段拼接）
     */
    private void setTranprojectFields(Tranproject_registrationDTO dto, Tranproject_registration project) {
        // 负责人工号转UID
        if (project.getAccount() != null && !project.getAccount().trim().isEmpty()) {
            User headUser = iUserService.getUserByAccount(project.getAccount());
            project.setHead(headUser.getUid());
        }

        // 多值字段用逗号拼接
        List<String> sourceEnterpriseCategory = dto.getSourceEnterpriseCategory();
        if (sourceEnterpriseCategory != null) {
            project.setSourceEnterpriseCategory(String.join(",", sourceEnterpriseCategory));
        } else {
            project.setSourceEnterpriseCategory("");
        }

        // 确保dto.getProjectSourceUnitId()不为null
        String projectSourceUnitId = dto.getProjectSourceUnitId();
        project.setProjectSourceUnitId(projectSourceUnitId != null ? projectSourceUnitId : "");
    }


    /**
     * 删除横向项目关联数据
     */
    private void deleteRelatedData(String projectId) throws IOException {
        // 删除关联量化分数
        iProjectQualificationService.remove(Wrappers.lambdaQuery(Project_Qualification.class)
                .eq(Project_Qualification::getProjectID, projectId));

        // 删除关联作者
        tranprojectauthorService.remove(Wrappers.lambdaQuery(Tranprojectauthor.class)
                .eq(Tranprojectauthor::getTregistrationid, projectId));

        // 删除关联文件
        List<Tranprojectfile> files = tranprojectfileService.list(Wrappers.lambdaQuery(Tranprojectfile.class)
                .eq(Tranprojectfile::getTregistrationID, projectId));
        for (Tranprojectfile file : files) {
            tranprojectfileService.deletTranprojectfile(file.getFileid());
        }

        // 删除到账经费
        dzZfundsService.remove(Wrappers.lambdaQuery(DZfunds.class)
                .eq(DZfunds::getTregistrationID, projectId));

        // 删除支出经费
        zcZfundsService.remove(Wrappers.lambdaQuery(ZCfunds.class)
                .eq(ZCfunds::getTregistrationID, projectId));

        // 删除审核记录
        auditService.remove(Wrappers.lambdaQuery(Audit.class)
                .eq(Audit::getSynthesisID, projectId));
    }


}